'use strict';

const mysql = require('mysql2/promise');
const fs = require('fs');
const path = require('path');

/**
 * MySQL服务，提供MySQL数据库操作
 */
class MySQL {
  /**
   * 构造函数
   */
  constructor() {

    this._connection = null;
    this._pool = null;
    this._config = this._loadConfig();
    this.isConnected = false;
    this._inTransaction = false;
  }

  /**
   * 加载MySQL配置
   * @returns {object} MySQL配置
   * @private
   */
  _loadConfig() {
    try {
      const baseConfigPath = path.resolve(process.cwd(), 'config/baseConfig.json');
      if (fs.existsSync(baseConfigPath)) {
        const configContent = fs.readFileSync(baseConfigPath, 'utf8');
        const config = JSON.parse(configContent);

        if (config.mysql) {
          // 设置默认值
          return {
            host: config.mysql.host || 'localhost',
            port: config.mysql.port || 3306,
            user: config.mysql.user || 'root',
            password: config.mysql.password || '',
            database: config.mysql.database || 'rpcserver',
            waitForConnections: true,
            connectionLimit: 10,
            queueLimit: 0,
            autoInitTables: config.mysql.autoInitTables !== false // 默认为true，除非明确设置为false
          };
        }
      }
    } catch (error) {
      console.error('[MySQL] 加载MySQL配置失败:', error);
    }

    // 返回默认配置
    return {
      host: 'localhost',
      port: 3306,
      user: 'root',
      password: '123789',
      database: 'rpcserver',
      waitForConnections: true,
      connectionLimit: 10,
      queueLimit: 0,
      autoInitTables: true
    };
  }

  /**
   * 初始化服务
   */
  async init() {
    console.log(`[MySQL] 服务初始化中...`);

    try {
      // 初始化数据库表结构
      if (this._config.autoInitTables !== false) {
        // 延迟导入初始化器，避免循环依赖
        const MySQLTableInitializer = require('./initTables');
        this._tableInitializer = new MySQLTableInitializer(this);

        // 尝试自动连接
        if (!this.isConnected) {
          const connected = await this.connect();
          if (!connected) {
            console.warn(`[MySQL] 自动连接失败，表初始化将延迟到手动连接后进行`);
            return;
          }
        }

        // 初始化表
        console.log(`[MySQL] 开始初始化数据库表...`);
        const result = await this._tableInitializer.initializeAllTables();
        if (result) {
          console.log(`[MySQL] 数据库表初始化完成`);
        } else {
          console.warn(`[MySQL] 数据库表初始化未完成，请检查日志`);
        }
      } else {
        console.log(`[MySQL] 自动表初始化已禁用`);
      }
    } catch (error) {
      console.error(`[MySQL] 初始化过程出错:`, error);
    }
  }

  /**
   * 连接到MySQL数据库
   * @param {object} [config] 可选的配置信息，覆盖默认配置
   * @returns {Promise<boolean>} 是否连接成功
   */
  async connect(config) {
    try {
      // 如果已经连接，先断开
      if (this.isConnected) {
        await this.disconnect();
      }

      // 合并配置
      if (config) {
        this._config = { ...this._config, ...config };
      }

      // 创建连接池
      this._pool = mysql.createPool(this._config);

      // 测试连接
      const connection = await this._pool.getConnection();
      this.isConnected = true;
      connection.release();

      console.log(`[MySQL] 已连接到MySQL服务器: ${this._config.host}:${this._config.port}`);
      return true;
    } catch (error) {
      console.error(`[MySQL] 连接错误:`, error);
      this.isConnected = false;
      return false;
    }
  }

  /**
   * 断开MySQL连接
   * @returns {Promise<boolean>} 是否断开成功
   */
  async disconnect() {
    try {
      if (this._pool) {
        await this._pool.end();
        this._pool = null;
      }
      this.isConnected = false;
      console.log(`[MySQL] 连接已关闭`);
      return true;
    } catch (error) {
      console.error(`[MySQL] 断开连接错误:`, error);
      return false;
    }
  }

  /**
   * 检查连接状态
   * @private
   */
  _checkConnection() {
    if (!this.isConnected || !this._pool) {
      throw new Error('MySQL未连接，请先调用connect方法');
    }
  }

  /**
   * 执行SQL查询
   * @param {string} sql SQL语句
   * @param {Array|Object} [values] 参数值
   * @returns {Promise<Array>} 查询结果
   */
  async query(sql, values) {
    this._checkConnection();
    try {
      if (this.isDebug) {
        Logger.debug(`[MySQL] 执行查询: ${sql}`);
        if (values) {
          Logger.debug(`[MySQL] 参数:`, values);
        }
      }

      const [rows] = await this._pool.query(sql, values);
      return rows;
    } catch (error) {
      Logger.error(`[MySQL] 查询错误:`, error);
      throw error;
    }
  }

  /**
   * 执行SQL语句
   * @param {string} sql SQL语句
   * @param {Array|Object} [values] 参数值
   * @returns {Promise<Object>} 执行结果
   */
  async execute(sql, values) {
    this._checkConnection();
    try {
      if (this.isDebug) {
        Logger.debug(`[MySQL] 执行SQL: ${sql}`);
        if (values) {
          Logger.debug(`[MySQL] 参数:`, values);
        }
      }

      const [result] = await this._pool.execute(sql, values);
      return result;
    } catch (error) {
      Logger.error(`[MySQL] 执行错误:`, error);
      throw error;
    }
  }

  /**
   * 开始事务
   * @returns {Promise<boolean>} 是否成功
   */
  async beginTransaction() {
    this._checkConnection();
    try {
      if (this._inTransaction) {
        throw new Error('事务已经开始');
      }

      this._connection = await this._pool.getConnection();
      await this._connection.beginTransaction();
      this._inTransaction = true;

      if (this.isDebug) {
        Logger.debug(`[MySQL] 开始事务`);
      }

      return true;
    } catch (error) {
      Logger.error(`[MySQL] 开始事务错误:`, error);
      if (this._connection) {
        this._connection.release();
        this._connection = null;
      }
      this._inTransaction = false;
      throw error;
    }
  }

  /**
   * 提交事务
   * @returns {Promise<boolean>} 是否成功
   */
  async commit() {
    try {
      if (!this._inTransaction || !this._connection) {
        throw new Error('没有活动的事务');
      }

      await this._connection.commit();
      this._connection.release();
      this._connection = null;
      this._inTransaction = false;

      if (this.isDebug) {
        Logger.debug(`[MySQL] 提交事务`);
      }

      return true;
    } catch (error) {
      Logger.error(`[MySQL] 提交事务错误:`, error);
      if (this._connection) {
        this._connection.release();
        this._connection = null;
      }
      this._inTransaction = false;
      throw error;
    }
  }

  /**
   * 回滚事务
   * @returns {Promise<boolean>} 是否成功
   */
  async rollback() {
    try {
      if (!this._inTransaction || !this._connection) {
        throw new Error('没有活动的事务');
      }

      await this._connection.rollback();
      this._connection.release();
      this._connection = null;
      this._inTransaction = false;

      if (this.isDebug) {
        Logger.debug(`[MySQL] 回滚事务`);
      }

      return true;
    } catch (error) {
      Logger.error(`[MySQL] 回滚事务错误:`, error);
      if (this._connection) {
        this._connection.release();
        this._connection = null;
      }
      this._inTransaction = false;
      throw error;
    }
  }

  /**
   * 查询单条记录
   * @param {string} sql SQL语句
   * @param {Array|Object} [values] 参数值
   * @returns {Promise<Object|null>} 查询结果
   */
  async queryOne(sql, values) {
    const rows = await this.query(sql, values);
    return rows.length > 0 ? rows[0] : null;
  }

  /**
   * 插入数据
   * @param {string} table 表名
   * @param {Object} data 数据对象
   * @returns {Promise<Object>} 插入结果
   */
  async insert(table, data) {
    this._checkConnection();
    try {
      const keys = Object.keys(data);
      const values = Object.values(data);
      const placeholders = keys.map(() => '?').join(', ');

      const sql = `INSERT INTO ${this.escapeId(table)} (${keys.map(k => this.escapeId(k)).join(', ')}) VALUES (${placeholders})`;

      return await this.execute(sql, values);
    } catch (error) {
      Logger.error(`[MySQL] 插入错误:`, error);
      throw error;
    }
  }

  /**
   * 更新数据
   * @param {string} table 表名
   * @param {Object} data 数据对象
   * @param {string|Object} where 条件
   * @returns {Promise<Object>} 更新结果
   */
  async update(table, data, where) {
    this._checkConnection();
    try {
      const keys = Object.keys(data);
      const values = Object.values(data);

      let sql = `UPDATE ${this.escapeId(table)} SET `;
      sql += keys.map(key => `${this.escapeId(key)} = ?`).join(', ');

      let whereClause = '';
      if (typeof where === 'string') {
        whereClause = where;
      } else if (typeof where === 'object') {
        const whereKeys = Object.keys(where);
        whereClause = whereKeys.map(key => `${this.escapeId(key)} = ?`).join(' AND ');
        values.push(...Object.values(where));
      }

      sql += ` WHERE ${whereClause}`;

      return await this.execute(sql, values);
    } catch (error) {
      Logger.error(`[MySQL] 更新错误:`, error);
      throw error;
    }
  }

  /**
   * 删除数据
   * @param {string} table 表名
   * @param {string|Object} where 条件
   * @returns {Promise<Object>} 删除结果
   */
  async delete(table, where) {
    this._checkConnection();
    try {
      let sql = `DELETE FROM ${this.escapeId(table)} WHERE `;
      let values = [];

      if (typeof where === 'string') {
        sql += where;
      } else if (typeof where === 'object') {
        const whereKeys = Object.keys(where);
        sql += whereKeys.map(key => `${this.escapeId(key)} = ?`).join(' AND ');
        values = Object.values(where);
      }

      return await this.execute(sql, values);
    } catch (error) {
      Logger.error(`[MySQL] 删除错误:`, error);
      throw error;
    }
  }

  /**
   * 计数
   * @param {string} table 表名
   * @param {string|Object} [where] 条件
   * @returns {Promise<number>} 记录数
   */
  async count(table, where) {
    this._checkConnection();
    try {
      let sql = `SELECT COUNT(*) as count FROM ${this.escapeId(table)}`;
      let values = [];

      if (where) {
        sql += ' WHERE ';
        if (typeof where === 'string') {
          sql += where;
        } else if (typeof where === 'object') {
          const whereKeys = Object.keys(where);
          sql += whereKeys.map(key => `${this.escapeId(key)} = ?`).join(' AND ');
          values = Object.values(where);
        }
      }

      const result = await this.queryOne(sql, values);
      return result ? result.count : 0;
    } catch (error) {
      Logger.error(`[MySQL] 计数错误:`, error);
      throw error;
    }
  }

  /**
   * 获取最后插入的ID
   * @returns {Promise<number>} 最后插入的ID
   */
  async getLastInsertId() {
    const result = await this.queryOne('SELECT LAST_INSERT_ID() as id');
    return result ? result.id : 0;
  }

  /**
   * 转义值
   * @param {string|number|boolean|Object} value 值
   * @returns {string} 转义后的值
   */
  escape(value) {
    return this._pool.escape(value);
  }

  /**
   * 转义标识符
   * @param {string} identifier 标识符
   * @returns {string} 转义后的标识符
   */
  escapeId(identifier) {
    return this._pool.escapeId(identifier);
  }

  /**
   * 执行SQL脚本文件
   * @param {string} scriptPath 脚本文件路径
   * @returns {Promise<boolean>} 是否成功
   */
  async executeScript(scriptPath) {
    this._checkConnection();
    try {
      const script = fs.readFileSync(scriptPath, 'utf8');
      const statements = script.split(';').filter(stmt => stmt.trim().length > 0);

      for (const statement of statements) {
        await this.execute(statement);
      }

      return true;
    } catch (error) {
      Logger.error(`[MySQL] 执行脚本错误:`, error);
      throw error;
    }
  }

  /**
   * 列出所有表
   * @returns {Promise<Array>} 表列表
   */
  async listTables() {
    return await this.query('SHOW TABLES');
  }

  /**
   * 描述表结构
   * @param {string} tableName 表名
   * @returns {Promise<Array>} 表结构
   */
  async describeTable(tableName) {
    return await this.query(`DESCRIBE ${this.escapeId(tableName)}`);
  }
}

module.exports = MySQL; 